package cn.coastalinfo.project.drools.utils;

import cn.coastalinfo.common.utils.StringUtils;
import cn.coastalinfo.project.drools.domain.Rule;
import cn.coastalinfo.project.drools.domain.RuleCondition;
import cn.coastalinfo.project.drools.enums.ConditionType;
import cn.coastalinfo.project.drools.enums.LeftAssignEnums;

import java.util.List;

public class DroolsRuleUtils {
    public static String rule2Drl(Rule rule,String condition) {
        StringBuilder result = new StringBuilder();
        /*package部分*/
//        result.append("package  com.drools.rules;\r\n");
        result.append("dialect \"mvel\";\r\n");
        result.append("\r\n");

        /*导包部分*/
        result.append("import cn.coastalinfo.project.drools.fact.RuleFact;\r\n");
        result.append("\r\n");

        /*规则申明部分*/
//        result.append("rule \"3333\"\r\n");
        result.append(String.format("rule \"%s\"\r\n", rule.getName()+System.currentTimeMillis()));

        /*规则属性部分*/
//        result.append(String.format("\tsalience  \"%s\"\r\n", rule.getSalience()));
        result.append("\tno-loop false\r\n");//禁止重复

        /*规则条件部分*/
        result.append("\twhen\r\n");
        result.append("\t\t$result:RuleFact()\r\n");
        result.append("\t\tRuleFact(\r\n");
        result.append(condition);
        result.append("\t\t)\r\n");

        /*规则结果部分*/
        result.append("\tthen\r\n");
        result.append(String.format("\t\tSystem.out.println(\"规则%s被触发了\");\r\n",rule.getName()));
        result.append(String.format("\t\t$result.add(\"%s\");\r\n", rule.getThenSet()));

        /*规则结束*/
        result.append("end\r\n");
        return result.toString();
    }

    /**
     * 获取条件或普通规则
     * @param rc
     * @return
     */
    public static String contion2Str(RuleCondition rc,RuleCondition parent) {
        if(rc.getType() == ConditionType.AND || rc.getType() == ConditionType.OR){
            if(rc.getChildren() == null || rc.getChildren().size()<1){
                return "";
            }
//            return ConditionType.AND.getCode();
//            if(parent != null && parent.getType() != ConditionType.NORMAL){
//                return parent.getType() == ConditionType.OR?"1!=1":"1==1";
//            }
            return "";
        }
        if(rc.getType() == ConditionType.NORMAL){
            //运算式左值右值
            String left = "1";String right = "1";
            if(rc.getLeftType() != null && rc.getLeftType().equals(LeftAssignEnums.Input.getCode()) ){
                if(">=<==".contains(rc.getOperator().getCode()) && rc.getLeftValue().matches("-?\\d+(\\.\\d+)?")){//保留数字
                    left = rc.getLeftValue();
                }else if("not contains".contains(rc.getOperator().getCode())){
                    left = String.format("getStrList(map[\"%s\"])",rc.getLeftValue());
                }else{
                    left = String.format("\"%s\"",rc.getLeftValue());
                }
            }
            if(rc.getLeftType() == null || rc.getLeftType().equals( LeftAssignEnums.Variable.getCode())){
                if(left.equals("1")){
                    left = String.format("map[\"%s\"]",rc.getLeftValue());
                }
                if("not contains".contains(rc.getOperator().getCode())){
                    left = String.format("getStrList(map[\"%s\"])",rc.getLeftValue());
                }
            }
            //右值
            if(rc.getRightType() == null || rc.getRightType().equals(LeftAssignEnums.Input.getCode())){
                if(">=<==".contains(rc.getOperator().getCode()) && rc.getRightValue().matches("-?\\d+(\\.\\d+)?")){//保留数字
                    right = rc.getRightValue();
                }else if("not member of".contains(rc.getOperator().getCode())){
                    right = String.format("getStrList(map[\"%s\"])",rc.getRightValue());
                }else{
                    right = String.format("\"%s\"",rc.getRightValue());
                }
            }
            if(rc.getRightType() != null && rc.getRightType().equals(LeftAssignEnums.Variable.getCode()) ){
                if(right.equals("1")){
                    right = String.format("map[\"%s\"]",rc.getLeftValue());
                }
                if("not member of".contains(rc.getOperator().getCode())){
                    right = String.format("getStrList(map[\"%s\"])",rc.getLeftValue());
                }
            }
            return String.format("%s %s %s", left,rc.getOperator().getCode(),right);
        }
        return "";
    }

    /**
     * 获取LHS
     * @param rc
     * @return
     */
    public static String contion2LHS(RuleCondition rc,StringBuilder str,int num,RuleCondition parent,String nextStr) {
        Boolean isRoot = rc.getType()!= ConditionType.NORMAL;
//        Boolean isRoot = rc.getChildren() != null && rc.getChildren().size()>1;
        String s = contion2Str(rc,parent);//条件
        if(StringUtils.isNotBlank(s)){
            String sk = "";
//            if(isRoot && rc.getChildren() != null && rc.getChildren().size()>1){
//            if(isRoot && parent.getChildren() != null && parent.getChildren().size()>1){
//                sk = "(";
//            }
            str.append("\t\t"+sk+getKong(num)+s);
            if(StringUtils.isNotBlank(nextStr) && parent !=null && parent.getChildren().size()>1){
                String opstr = parent.getType().getCode().equals("or") ? "||":"&&";
                str.append("\r\n\t\t"+sk+getKong(num)+"\t\t"+opstr);
            }
            str.append("\r\n");
        }else if(isRoot && rc.getChildren() != null && rc.getChildren().size()>1  && checkRules(rc.getChildren())){
//            //判断（之前是否添加 分隔符 与或
//            if(rnum > 0 &&rnum == num +1 && parent !=null && parent.getChildren().size()>1){
////            if(rnum > 0 &&rnum == num +1 ){
//                String rootop =   parent.getType().getCode().equals("or") ? "||":"&&";
//                str.append("\t\t"+getKong(num)+rootop);
//                str.append("\r\n");
//            }
            str.append("\t\t"+getKong(num)+"(");
            str.append("\r\n");
//            rnum = 0;
        }
        if(isRoot){
            num+=1;
        }
        if (rc.getChildren() != null) {
//            for (RuleCondition child : rc.getChildren()) {
            for (int i = 0; i < rc.getChildren().size(); i++) {
                boolean isNext = i < rc.getChildren().size() - 1;
                String nextcontion = isNext?contion2Str(rc.getChildren().get(i+1),rc) : "";//下一个获取
                RuleCondition child = rc.getChildren().get(i);
                Boolean iscRoot = child.getType()!= ConditionType.NORMAL;
//                if(iscRoot){
//                    rnum +=1;
//                }
                String oldstr = str.toString();
                String buildStr = contion2LHS(child,str,num,rc,nextcontion); // 递归插入孙节点，以此类推

                RuleCondition nchild = isNext?rc.getChildren().get(i+1):null;
                //判断（之前是否添加 分隔符 与或
                if((nchild != null && ( ( iscRoot ) || ( nchild.getType()!= ConditionType.NORMAL) ) )  && (!buildStr.equals(oldstr)) && StringUtils.isNotBlank(contion2LHS(nchild,new StringBuilder(),0,null,"")) ){
                    String rootop =   rc.getType().getCode().equals("or") ? "||":"&&";
                    str.append("\t\t"+getKong(num)+rootop);
                    str.append("\r\n");
                }
            }
        }
        if(isRoot && rc.getChildren() != null && rc.getChildren().size()>1 && checkRules(rc.getChildren())){
            str.append("\t\t"+getKong(num-1)+")\r\n");
        }
        return str.toString();
    }

    /**
     * 获取 num 个空格符
     * @param num
     * @return
     */
    public static String getKong(int num) {
        String str = "";
        for(int i = 0; i < num; i++){
            str +="\t";
        }
        return str;
    }

    /**
     * 判断是否含有真正的条件集
     * @param list
     * @return
     */
    public static boolean checkRules(List<RuleCondition> list) {
        if(list == null){
            return false;
        }
        for (RuleCondition child : list) {
            if(child.getType()== ConditionType.NORMAL){
                return true;
            }
        }
        return false;
    }
}
